package com.zb.mobile.user.service.impl;

import cn.dev33.satoken.stp.SaLoginModel;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zb.constant.AccountConstant;
import com.zb.entity.AccounLoginInfo;
import com.zb.entity.AccountLoginToken;
import com.zb.entity.ZjCustomer;
import com.zb.entity.ZjUser;
import com.zb.enums.DeviceType;
import com.zb.exception.SMSException;
import com.zb.mobile.user.service.ConUserMobileService;
import com.zb.redis.RedisUserLoginTokenUtil;
import com.zb.result.PageUtil;
import com.zb.secure.BCryptUtil;
import com.zb.util.MobileUserSmsUtil;
import com.zb.service.ZjCustomerService;
import com.zb.service.ZjUserService;
import com.zb.stp.StpUserUtil;
import com.zb.utils.TokenUserUtil;
import com.zb.vo.UserLoginVo;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.security.auth.login.LoginException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @Author WEN
 * @Date 2023/10/31 0031
 **/
@Service
public class ConUserMobileServiceImpl implements ConUserMobileService {
    @Resource
    private ZjUserService userService;
    @Resource
    private ZjCustomerService customerService;

    // 用户移动端登录
    @Override
    public AccountLoginToken login(Long custAccId, UserLoginVo loginVo) throws LoginException, SMSException {
        ZjUser user = null;
        if (1 == loginVo.getType()) {
            Assert.isTrue(StringUtils.isNotBlank(loginVo.getCode()), "验证码不能为空");
            // 校验验证码
            MobileUserSmsUtil.checkLoginVerificCode(loginVo.getPhone(), loginVo.getCode());
            user = userService.getByPhone(custAccId, loginVo.getPhone());
        }
        if (2 == loginVo.getType()) {
            Assert.isTrue(StringUtils.isNotBlank(loginVo.getPassword()), "登录密码不能空");

            user = userService.getByPhone(custAccId, loginVo.getPhone());
            if (null != user) {
                Assert.isTrue(Objects.equals(user.getPassword(), BCryptUtil.encryPassword(loginVo.getPassword(), user.getSalt())), "账号或密码错误");
            }
        }
        if (null != user) {
            if (user.getStatus() == 1) {
                Assert.isTrue(false, "账号已被冻结");
            }
            if (user.getStatus() == 2) {
                Assert.isTrue(false, "账号已被注销");
            }
        }
        // 注册账号并登录
        if (null == user && loginVo.isAccountRegistLogin()) {
            Assert.isTrue(StringUtils.isNotBlank(loginVo.getPassword()), "登录密码不能空");
            Assert.isTrue(loginVo.getPassword().length() >= 6, "请输入至少六位数的密码");
            user = userService.save(custAccId, loginVo.getPhone(), loginVo.getPassword());
        }

        if (StpUserUtil.isLogin(user.getId())) {
            String oldAccessToken = StpUserUtil.getTokenValueByLoginId(user.getId(), DeviceType.ORDER_MOBILE.name());
            // 删除旧的登录缓存信息
            RedisUserLoginTokenUtil.removeAllTokenByAccessToken(oldAccessToken);
            RedisUserLoginTokenUtil.removeLoginAccessToken(oldAccessToken);
        }
        StpUserUtil.login(user.getId(), new SaLoginModel()
                .setTimeout(AccountConstant.LOGIN_TOKEN_REMEMBERME_EXPIRE_TIME)
                .setDevice(DeviceType.ORDER_MOBILE.name())
        );
        // 更新最后登录时间
        userService.updatelastLoginTimeByLogin(user.getId());

        ZjCustomer customer = customerService.getById(custAccId);

        AccounLoginInfo accounLoginInfo = new AccounLoginInfo(user.getId(), user.getAccount(), user.getPhone(), user.getName(), DeviceType.ORDER_MOBILE.name());
        accounLoginInfo.setCustAccId(custAccId);
        accounLoginInfo.setCustAccLogoCode(customer.getLogoCode());
        accounLoginInfo.setCustAccAnnexCode(customer.getAnnexCode());
        accounLoginInfo.setCustAccVideoCode(customer.getVideoCode());
        return TokenUserUtil.getLoginToken(accounLoginInfo);
    }

    // 刷新登录Token
    @Override
    public AccountLoginToken refreshToken(String refreshToken) throws LoginException {
        if (!RedisUserLoginTokenUtil.hasAccessTokenByRefreshToken(refreshToken)) {
            throw new LoginException("登录已过期，请重新登录！");
        }
        // 旧token
        String oldAccessToken = RedisUserLoginTokenUtil.getAccessTokenByRefreshToken(refreshToken);
        AccounLoginInfo admInfo = RedisUserLoginTokenUtil.getAccountLoginInfoByAccessToken(oldAccessToken);

        // 退出旧的登录
        StpUserUtil.logout(admInfo.getId(), admInfo.getDevice());

        StpUserUtil.login(admInfo.getId(),
                new SaLoginModel()
                        .setDevice(admInfo.getDevice()) // 登录设备
                        .setIsLastingCookie(admInfo.isRememberMe()) // 记住我
                        .setTimeout(AccountConstant.LOGIN_TOKEN_REMEMBERME_EXPIRE_TIME) // 七天有效期
        );
        // 删除旧的登录缓存信息
        RedisUserLoginTokenUtil.removeAllTokenByAccessToken(oldAccessToken);
        RedisUserLoginTokenUtil.removeLoginAccessToken(oldAccessToken);
        return TokenUserUtil.getLoginToken(admInfo);
    }

    // 获取当前客户登录信息
    @Override
    public Map<String, Object> getUerDetail(Long userId) {
        ZjUser user = userService.getById(userId);
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("phone", null == user? "" : user.getPhone());
        resultMap.put("account", null == user? "" : user.getAccount());
        resultMap.put("name", null == user? "" : user.getName());
        resultMap.put("nickname", null == user? "" : user.getNickname());
        resultMap.put("status", null == user? "" : user.getStatus());
        resultMap.put("lastLoginTime", null == user? "" : user.getLastLoginTime());
        resultMap.put("avatar", null == user? "" : user.getAvatar());
        resultMap.put("bindingWechat", false); // TODO 是否绑定微信
        return PageUtil.row(resultMap);
    }

    // 注销账号
    @Override
    public void cancelAccount(AccounLoginInfo loginInfo) {
        ZjUser user = new ZjUser();
        user.setId(loginInfo.getId());
        user.setStatus(2);
        userService.updateById(user);
    }
}
